// Fill out your copyright notice in the Description page of Project Settings.

#include "AdvancedCharacterMovementComponent.h"
#include "Runtime/Engine/Classes/Kismet/KismetMathLibrary.h"
#include "Math/UnrealMathUtility.h" // 添加FMath的头文件包含

// 定义日志分类
DEFINE_LOG_CATEGORY(LogAdvancedMovement);

UAdvancedCharacterMovementComponent::UAdvancedCharacterMovementComponent()
{
    // 初始化变量
    bIsSprinting = false;
    SprintSpeedMultiplier = 1.5f;
    MaxSprintTime = 5.0f;
    SprintRecoveryRate = 0.25f; // 每秒恢复25%的冲刺时间
    CurrentSprintTimeRemaining = MaxSprintTime;
    GroundCheckRayCount = 3;
    
    // 记录组件初始化
    UE_LOG(LogAdvancedMovement, Log, TEXT("Component initialized"));
}

void UAdvancedCharacterMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    // 检查组件是否有效且已启用
    if (!IsValid(this) || !IsComponentTickEnabled())
    {
        return;
    }
    
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
    
    // 确保更新只在移动组件有效时进行
    if (CharacterOwner && UpdatedComponent)
    {
        // 更新冲刺状态
        UpdateSprint(DeltaTime);
        
        // 可以在这里添加其他自定义移动逻辑
    }
}

void UAdvancedCharacterMovementComponent::SetSprinting(bool bNewSprinting)


{
    // 只有当角色在地面上且有剩余冲刺时间时才能开始冲刺
    if (bNewSprinting)
    {
        if (IsMovingOnGround() && CurrentSprintTimeRemaining > 0.0f)
        {
            bIsSprinting = true;
            UE_LOG(LogAdvancedMovement, Log, TEXT("Sprint started"));
        }
        else
        {
            // 记录无法冲刺的原因
            if (!IsMovingOnGround())
            {
                UE_LOG(LogAdvancedMovement, Log, TEXT("Cannot sprint - not on ground"));
            }
            else if (CurrentSprintTimeRemaining <= 0.0f)
            {
                UE_LOG(LogAdvancedMovement, Log, TEXT("Cannot sprint - out of stamina"));
            }
        }
    }
    else
    {
        bIsSprinting = false;
        UE_LOG(LogAdvancedMovement, Log, TEXT("Sprint stopped"));
    }
}

bool UAdvancedCharacterMovementComponent::IsSprinting() const
{
    return bIsSprinting;
}

float UAdvancedCharacterMovementComponent::GetMaxSprintTime() const
{
    return MaxSprintTime;
}

float UAdvancedCharacterMovementComponent::GetCurrentSprintTimeRemaining() const
{
    return CurrentSprintTimeRemaining;
}

float UAdvancedCharacterMovementComponent::GetMaxSpeed() const
{
    float BaseMaxSpeed = Super::GetMaxSpeed();
    
    // 如果正在冲刺，应用冲刺速度倍率
    if (bIsSprinting)
    {
        return BaseMaxSpeed * SprintSpeedMultiplier;
    }
    
    return BaseMaxSpeed;
}

void UAdvancedCharacterMovementComponent::UpdateCharacterStateBeforeMovement(float DeltaTime)
{
    Super::UpdateCharacterStateBeforeMovement(DeltaTime);
    
    // 应用增强的地面检测
    // 注意：这只是示例，实际应用中可能需要更复杂的逻辑来整合增强检测与引擎内置检测
    if (MovementMode == MOVE_Falling && EnhancedGroundCheck())
    {
        // 可以在这里添加逻辑，在某些情况下将角色从下落模式切换回行走模式
        // 注意：直接修改MovementMode可能会干扰引擎内置的移动逻辑
        // 实际应用中应该考虑使用更合适的方法来处理这种情况
            UE_LOG(LogAdvancedMovement, Log, TEXT("Enhanced ground check detected walkable surface"));
    }
    
    // 可以在这里添加其他自定义的移动状态更新逻辑
    // 例如，根据地形调整移动参数等
}

void UAdvancedCharacterMovementComponent::UpdateSprint(float DeltaTime)
{
    if (bIsSprinting)
    {
        // 减少冲刺时间
        CurrentSprintTimeRemaining -= DeltaTime;
        
        // 如果冲刺时间用完，停止冲刺
        if (CurrentSprintTimeRemaining <= 0.0f)
        {
            CurrentSprintTimeRemaining = 0.0f;
            SetSprinting(false);
            UE_LOG(LogAdvancedMovement, Log, TEXT("Sprint ended - out of stamina"));
        }
    }
    else if (CurrentSprintTimeRemaining < MaxSprintTime && IsMovingOnGround())
    {
        // 恢复冲刺时间（只有在地面上且未冲刺时恢复）
        float RecoveryAmount = MaxSprintTime * SprintRecoveryRate * DeltaTime;
        CurrentSprintTimeRemaining = FMath::Min(CurrentSprintTimeRemaining + RecoveryAmount, MaxSprintTime);
    }
}

bool UAdvancedCharacterMovementComponent::EnhancedGroundCheck()
{
    // 基础地面检测结果
    bool BaseGroundCheck = IsMovingOnGround();
    
    // 如果基础检测已经认为在地面上，直接返回true
    if (BaseGroundCheck)
    {
        return true;
    }
    
    // 确保组件和角色所有者有效
    if (!CharacterOwner || !UpdatedComponent)
    {
        return false;
    }
    
    // 高级地面检测逻辑：使用多个射线进行更精确的地面检测
    FVector CapsuleLocation = UpdatedComponent->GetComponentLocation();
    float CapsuleRadius = GetCapsuleRadius();
    float CapsuleHalfHeight = GetCapsuleHalfHeight();
    
    // 射线检测参数
    FCollisionQueryParams QueryParams;
    QueryParams.AddIgnoredActor(CharacterOwner);
    QueryParams.bTraceComplex = false;
    
    // 射线长度（略大于胶囊体半高，确保检测到地面）
    const float RayLength = CapsuleHalfHeight * 1.2f;
    
    // 创建多个射线检测点
    TArray<FVector> RayStartLocations;
    RayStartLocations.Add(CapsuleLocation); // 中心射线
    
    // 根据配置的射线数量添加额外的射线点
    const float AngleIncrement = 360.0f / GroundCheckRayCount;
    for (int32 i = 1; i < GroundCheckRayCount; i++)
    {
        float AngleRad = FMath::DegreesToRadians(AngleIncrement * i);
        FVector SideOffset = FVector(Cos(AngleRad) * CapsuleRadius, Sin(AngleRad) * CapsuleRadius, 0.0f);
        RayStartLocations.Add(CapsuleLocation + SideOffset);
    }
    
    // 执行射线检测
    for (const FVector& RayStart : RayStartLocations)
    {
        FVector RayEnd = RayStart - FVector::UpVector * RayLength;
        FHitResult HitResult;
        
        if (GetWorld()->LineTraceSingleByChannel(HitResult, RayStart, RayEnd, ECC_Visibility, QueryParams))
        {
            // 如果射线检测到有效表面
            if (HitResult.bBlockingHit && HitResult.GetActor() != CharacterOwner)
            {
                // 检查表面法线，确保角度合适（不是太陡峭）
                float SurfaceSlope = FVector::DotProduct(HitResult.Normal, FVector::UpVector);
                if (SurfaceSlope >= FMath::Cos(FMath::DegreesToRadians(GetWalkableFloorAngle())))
                {
                    return true;
                }
            }
        }
    }
    
    return false;
}